package dk.au.cs.peterbn.patterns;

import java.util.*;

/**
 * Descriptor of the role a type can play
 */
public interface TypeRole extends HasDescription{

    /**
     * Get the MemberRole with the specified name
     * @param role Member role name
     * @return the requested MemberRole or <code>null</code> if it couldn't be found
     */
    MemberRole getMember(String role);

    String getName();

    /**
     * Get all the direct parent roles of this TypeRole.
     * This is the TypeRoles of the classes and interfaces that a class annotated with this typerole must be extending
     * @return Direct parent typeroles
     */
    Collection<TypeRole> getParentRoles();


    /**
     * The target is an abstraction of the type kind that
     * this role is intended to be.
     * The possible values is abstract and concrete, to
     * signify the difference between abstract classes and interfaces on one side
     * and concrete classes on the other side.
     * The original GOF book only operated with abstract classes,
     * as interfaces didn't exist at the time of writing. Nowadays, a
     * target value of ABSTRACT should be taken to mean an interface in most situations.
     */
    public static enum Target {
        ABSTRACT,
        CONCRETE,
        ANY;

        public static Target get(String name) {
            if (ABSTRACT.name().equalsIgnoreCase(name)) {
                return ABSTRACT;
            } else if (CONCRETE.name().equalsIgnoreCase(name)) {
                return CONCRETE;
            } else if (ANY.name().equalsIgnoreCase(name)) {
                return ANY;
            }
            return null;
        }

    }

    /**
     * Returns the set of TypeRoles that implement this this TypeRole.
     *
     * A non-empty set means that any class subclassing a type annotated
     * with this typeRole must play the role of all the implementing TypeRoles,
     * either through inheritance or directly and must be annotated with all of them.
     *
     * @return the set of TypeRoles that implement this this TypeRole
     */
    public Set<TypeRole> getImplementers();

    /**
     * Get the containing pattern for this TypeRole
     * @return The containing pattern
     */
    public abstract DesignPattern getPattern();

    /**
     * @return The canonical member names for this type.
     */
    public abstract Map<String, MemberRole> getMembers();

    /**
     * @return Get the relations that are present in this type.
     */
    public Collection<? extends TypeRelation> getRelations();

    /**
     * @return The legal target of this role
     */
    public Target getTarget();


}
